[AWS IoT Events] 少しだけ複雑な条件式で探知機モデルを作成してみました
1 はじめに
CX事業本部の平内(SIN)です。
昨日、AWS IoT Events(以下、IoT Events)で起動したLambdaへ送られるPayloadについて確認してみましたが、作成した、温度管理の探知機は、単純に指定した温度を超えたかどうかで状態が遷移するものでした。
今回は、条件式の変数や式を、少し複雑なものにして試してみました。
考えた動作は、以下のようなものです。
- 温度の最高値及び、最低値を記録
- 記録された最高・最低値と比較して10度以上の変化を検出した場合に「異常状態」に遷移してアラート
- 「異常状態」から「正常状態」への復帰は、初期化メッセージで行う
イメージとしては、温度デバイスの故障を検出する探知機です。
2 入力モデル
今回は、初期化用のフラグが、新たに必要になったため、入力を新たに設定しました。
SampleDetectorModelInput2.json
{ "deviceName": "", "temp" : "", "init" : "" }
名前は、SampleDetectorModelInput2となっています。
3 探知機モデル
前回とほぼ同じで、2つの状態(Normal及び、Abnormal)とその間の相互の移行が定義されています。
設定されたイベントは、色々変わっています。
(1) Normal状態のイベント
Normal状態のOnInputには、以下の3つのイベントが定義されています。
- initialize
- updateMaxTemp
- updateMinTemp
initializeでは、ディテクターの初期化が行われます。
イベントの条件は、initに"true"が入っている事です。
$input.SampleDetectorModelInput2.init == "true"
ここでのイベントアクションとしては、変数の初期化を行われています。
- MaxTemp = -999
- MinTemp = 999
updateMaxTempは、最大値の更新です。
イベントの条件は、maxTempが初期値の場合、若しくは、maxTempより、大きな値で、10度以内の変化の場合です。
イベントアクションでMaxTempが更新されます。
$variable.maxTemp == -999 || ($input.SampleDetectorModelInput2.temp < $variable.maxTemp +10 && $variable.maxTemp < $input.SampleDetectorModelInput2.temp)
updateMinTempは、最小値の更新です。
イベントの条件は、minTempが初期値の場合、若しくは、minTempより、小さな値で、10度以内の変化の場合です。
イベントアクションとして、MinTempが更新されます。
$variable.minTemp == 999 || ($variable.minTemp -10 < $input.SampleDetectorModelInput2.temp && $input.SampleDetectorModelInput2.temp < $variable.minTemp)
(2) toAbnormal遷移
toAbnormalの遷移条件は、以下のとおりです。
「maxTempが初期値でない」かつ「minTempが初期値でない」かつ「maxTempより10度以上高い 若しくは、minTempより10度以上低い」
$variable.maxTemp != -999 && $variable.minTemp != 999 &&($input.SampleDetectorModelInput2.temp >= $variable.maxTemp + 10 || $input.SampleDetectorModelInput2.temp <= $variable.minTemp - 10)
また、この時点の温度値(Temp)をアラートに出力できるように、変数Tempに記録しています。
(3) toNormal遷移
toNormalの遷移条件は、init に "true" が設定されているかどうかだけです。
$input.SampleDetectorModelInput2.init == "true"
(4) Abnormalのイベント
Abnormalのイベントには、Lambdaの発火が定義されていますが、こちらは、前回と同じです。
4 メッセージ送信
メッセージを送信して、探知機の動作を確認するのに、簡単なプログラムを作成しました。
iotevents-dataのbatch_put_messageを使用しています。
from boto3.session import Session import uuid import json # メッセージ送信 def putMessage(profile, inputName, payload): session = Session(profile_name=profile) client = session.client('iotevents-data') messageId = str(uuid.uuid4()) response = client.batch_put_message( messages=[ { 'messageId': messageId, 'inputName': inputName, 'payload': json.dumps(payload).encode() }, ] ) return response profile = 'developer' inputName = "SampleDetectorModelInput2" deviceName = "device001" # 初期化 response = putMessage(profile, inputName, { "deviceName":deviceName, "init": "true", }) print(response) # 温度変化 # temps = [20, 25, 15, 40] temps = [20, 25, 20, 15, 10, 6, 35] for temp in temps: response = putMessage(profile, inputName, { "deviceName":deviceName, "temp": temp, }) print(response)
5 動作確認
(1) テスト1
初期化の後、20, 25, 15, 40と送った場合の送信メッセージと変数・状態の変化です。
(送)init | (送)Temp | maxTemp | minTemp | Temp | 状態 |
---|---|---|---|---|---|
true | - | -999 | 999 | - | Normal |
- | 20 | 20 | 20 | - | Normal |
- | 25 | 25 | 20 | - | Normal |
- | 15 | 25 | 15 | - | Normal |
- | 40 | 25 | 15 | 40 | Abnormal |
結果は、Lambdaに送られたペイロードで確認しました。
(2) テスト2
初期化の後、20, 25, 20, 15, 10, 6, 35と送った場合の送信メッセージと変数・状態の変化です。
(送)init | (送)Temp | maxTemp | minTemp | Temp | 状態 |
---|---|---|---|---|---|
true | - | -999 | 999 | - | Normal |
- | 20 | 20 | 20 | - | Normal |
- | 25 | 25 | 20 | - | Normal |
- | 15 | 25 | 15 | - | Normal |
- | 10 | 25 | 10 | - | Normal |
- | 6 | 25 | 6 | - | Normal |
- | 35 | 25 | 6 | 35 | Abnormal |
こちらも想定通り動作しているようです。
6 最後に
今回は、探知機の条件式を少し複雑なものにして試してみました。
色々と組み込む事も可能ですが、あんまり凝ったものになると、コーディングなしと言い切れなくなってくるかも知れません。しかし、IoT Eventsだけで完結できれば、別途、DynamoDBなどを使用するのに比べると、料金的なメリットはあると思います。
ちょっと検討しきれてませんが・・・条件式は、状態の種類を増やす事で、もう少し、簡略化できそうな気もしてます。